"use strict";

exports.slim=function(o, names)
{
  var x;
  var name;

  var obj={};

  for(x=0; x<names.length; x++)
  {
    name=names[x];
    obj[name]=o[name];
  }

  return obj;
}

exports.instantiate=function(f, args, o)
{
  f.prototype=o;
  return new f(args);
}

exports.create=function(o)
{
  function f() {}
  f.prototype=o;
  return new f();
}

exports.cloneArray=function(a)
{
  var result=[];
  var i;

  for(i=0; i<a.length; i++)
  {
    result.push(a[i]);
  }

  return result;
}

exports.clone=function(p)
{
  var o=(p instanceof Array) ? [] : {};
  var propName;

  if(p.prototype!==undefined)
  {
    o.prototype=p.prototype;
  }

  for(propName in p)
  {
    if(p.hasOwnProperty(propName))
    {
      o[propName]=p[propName];
    }
  }

  return o;
}

exports.merge=function()
{
  var objs=arguments;
  var o={};

  for(var x=0; x<objs.length; x++)
  {
    var obj=objs[x];
    for(var propName in obj)
    {
      if(obj.hasOwnProperty(propName))
      {
        var prop=obj[propName];
        if(typeof prop=='function')
        {
          o[propName]=prop;
        }
        else
        {
          o[propName]=prop;
        }
      }
    }
  }

  return o;
}

function delegate(src, dst, propName)
{
  var prop=src[propName];

  dst[propName]=function() {
    return prop.apply(src, arguments);
  };
}

// Remember, no block scoping, only function scoping
exports.bundle=function()
{
  var objs=arguments;
  var o={};
  var x;
  var obj;
  var propName;
  var prop;

  for(x=0; x<objs.length; x++)
  {
    obj=objs[x];
    for(propName in obj)
    {
      prop=obj[propName];
      if(typeof prop=='function')
      {
        delegate(obj, o, propName);
      }
      else
      {
        o[propName]=prop;
      }
    }
  }

  return o;
}

function delegate2(src, dst, propName)
{
  var prop=src[propName];

  dst[propName]=function() {
    return prop.apply(dst, arguments);
  };
}

// Remember, no block scoping, only function scoping
exports.bundle2=function()
{
  var objs=arguments;
  var o={};
  var x;
  var obj;
  var propName;
  var prop;

  for(x=0; x<objs.length; x++)
  {
    obj=objs[x];
    for(propName in obj)
    {
      prop=obj[propName];
      if(typeof prop=='function')
      {
        delegate2(obj, o, propName);
      }
      else
      {
        o[propName]=prop;
      }
    }
  }

  return o;
}

// Remember, no block scoping, only function scoping
exports.bundle3=function()
{
  var objs=arguments;
  var o={};
  var x;
  var obj;
  var propName;
  var prop;

  for(x=0; x<objs.length; x++)
  {
    obj=objs[x];
    for(propName in obj)
    {
      prop=obj[propName];
      if(typeof prop=='function')
      {
        delegate(obj, o, propName);
      }
    }
  }

  return o;
}

// Remember, no block scoping, only function scoping
exports.bundle4=function()
{
  var objs=arguments;
  var o={};
  var x;
  var obj;
  var propName;
  var prop;

  for(x=0; x<objs.length; x++)
  {
    obj=objs[x];
    for(propName in obj)
    {
      prop=obj[propName];
      if(typeof prop=='function')
      {
        delegate2(obj, o, propName);
      }
    }
  }

  return o;
}
